﻿using Agile.Infra.SqlSugar;

namespace Microsoft.Extensions.DependencyInjection;

public static class ServiceCollectionExtensions
{
    //*************************************************************
    //  appsettings.json 配置示例：
    //
    // "SqlSugar": {
    //    "DbType": "MySql",
    //    "EnabledLog": true,
    //    "ConnectionString": "server=127.0.0.1;port=3306;user id=test;password=test;database=test;CharSet=utf8mb4;allow zero datetime=true;Convert Zero Datetime=true;"
    // },
    //
    //************************************************************* 
    public static IServiceCollection AddAgileSqlSugar(this IServiceCollection services, IConfigurationSection section)
    {
        if (services.HasRegistered(nameof(AddAgileSqlSugar)))
            return services;

        var sqlSugarOptions = section.Get<SqlSugarOptions>();
        services.AddSingleton<ISqlSugarClient>(o =>
        {
            var config = new ConnectionConfig()
            {
                ConnectionString = sqlSugarOptions.ConnectionString,
                DbType = GetDbType(sqlSugarOptions.DbType),
                IsAutoCloseConnection = true,
                LanguageType = LanguageType.Chinese,
                MoreSettings = new ConnMoreSettings
                {
                    IsAutoRemoveDataCache = true
                }
            };

            if (sqlSugarOptions.EnabledLog)
                WriteSqlLog(o, config);

            return new SqlSugarScope(config, db =>
            {
                db.QueryFilter.AddTableFilter<IDeleted>(it => it.IsDeleted == false);
            });
        });
        return services;
    }

    private static void WriteSqlLog(IServiceProvider serviceProvider, ConnectionConfig config)
    {
        string GetParas(SugarParameter[] pars)
        {
            string key = "【SQL参数】：";
            foreach (var param in pars)
            {
                key += $"{param.ParameterName}:{param.Value}\n";
            }
            return key;
        }
        string GetSqlLog(string sql, SugarParameter[] pars) => $"【SQL语句】：{sql}\n{GetParas(pars)}";

        var logger = serviceProvider.GetService(typeof(ILogger<ISqlSugarClient>)) as ILogger;
        config.AopEvents = new AopEvents
        {
            OnLogExecuting = (sql, p) =>
            {
                logger.LogInformation(GetSqlLog(sql, p));
            },
            OnError = (ex) =>
            {
                logger.LogError($"【SQL报错】：{ex.Message}\n{GetSqlLog(ex.Sql, ex.Parametres as SugarParameter[])}");
            }
        };
    }

    private static DbType GetDbType(string dbType)
    {
        dbType = dbType.ToLower();

        switch (dbType)
        {
            case "mysql": return DbType.MySql;
            case "sqlserver": return DbType.SqlServer;
            case "sqlite": return DbType.Sqlite;
            case "oracle": return DbType.Oracle;
            case "postgresql": return DbType.PostgreSQL;
            case "dm": return DbType.Dm;
            case "kdbndp": return DbType.Kdbndp;
            case "oscar": return DbType.Oscar;
            case "access": return DbType.Access;
            case "opengauss": return DbType.OpenGauss;
            case "questdb": return DbType.QuestDB;
            case "hg": return DbType.HG;
            case "clickhouse": return DbType.ClickHouse;
            case "gbase": return DbType.GBase;
            case "odbc": return DbType.Odbc;
            case "custom": return DbType.Custom;
        }

        throw new Exception($"无效的数据库类型:{dbType}");
    }
}